package com.xyht.sca_s.student_manage_system.modules.tips.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.SmsTips;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.SmsTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.req.SmsTipsRecordReq;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.resp.SmsApplicationTipsResp;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.resp.SmsTipsAndDetailResp;
import com.xyht.sca_s.student_manage_system.modules.tips.entity.resp.SmsTipsResp;
import com.xyht.sca_s.student_manage_system.modules.tips.mapper.SmsTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.tips.mapper.SmsTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.tips.mapper.SmsTipsRecordMpjMapper;
import com.xyht.sca_s.student_manage_system.modules.tips.service.SmsTipsService;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsApplication;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsApplicationMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.tips.constant.TipsDoneFlagConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.tips.constant.TipsIsAllFlagConstant.TIPS_ONE;
import static com.xyht.sca_s.student_manage_system.modules.tips.constant.TipsTypeConstant.TIPS_TYPE_MESSAGE;

/**
 * <p>
 * 消息通知与待办 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-02-05
 */
@Service
public class SmsTipsServiceImpl extends ServiceImpl<SmsTipsMapper, SmsTips> implements SmsTipsService {
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private SmsTipsMapper smsTipsMapper;
    @Autowired
    private SmsTipsRecordMapper smsTipsRecordMapper;
    @Autowired
    private SmsApplicationMapper smsApplicationMapper;
    @Autowired
    private SmsTipsRecordMpjMapper smsTipsRecordMpjMapper;


    @Override
    public ResponseResult getAppTips(String user_id, Integer client, Integer type) {
        List<SmsApplication> appList = cacheUtil.getAppNameList(user_id, client);
        List<SmsApplicationTipsResp> appTipsList = new ArrayList<>();
        if (appList.size() > 0) {
            appTipsList = appList.stream().map(smsApplication -> {
                SmsApplicationTipsResp applicationTipsResp = new SmsApplicationTipsResp();
                BeanUtils.copyProperties(smsApplication, applicationTipsResp);

                //查看每个应用对应未读消息待办
                Map<String,Object> map = getTipsRespList(user_id, type, TIPS_NOT_DONE, 1, 10,
                        client, smsApplication.getAppType());
                List<SmsTipsResp> resultList = JSONObject.parseArray(JSON.toJSONString(map.get("list")),SmsTipsResp.class);
                Integer total = (Integer) map.get("total");
                applicationTipsResp.setTipsNum(total);
                if (resultList.size() > 0) {
                    applicationTipsResp.setTipsResp(resultList.get(0));
                }
                return applicationTipsResp;
            }).collect(Collectors.toList());
        }

        return CommonResult.success(appTipsList);
    }

    @Override
    public ResponseResult getAppTipsDetail(String user_id, Integer type) {
        return null;
    }

    @Override
    @Transactional
    public ResponseResult getTipsList(String user_id, Integer type, Integer is_done,
                                      Integer pageNum, Integer pageSize, Integer client,
                                      String app_type) {
//        if (isNullOrEmpty(is_done)) {
//            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
//        }
        List<SmsTipsResp> tipsRespList;
        int total;
        List<SmsApplication> appList = cacheUtil.getAppNameList(user_id, client);
        List<String> appTypeList = appList.stream().map(SmsApplication::getAppType).distinct().collect(Collectors.toList());

        MPJLambdaWrapper<SmsTipsRecord> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SmsTipsRecord.class)
                .selectAll(SmsTips.class)
                .selectAs(SmsTipsRecord::getId, "recordId")
                .leftJoin(SmsTips.class, SmsTips::getId, SmsTipsRecord::getTipsId)
                .eq(SmsTipsRecord::getUserId, user_id);

        if (!isNullOrEmpty(is_done)) {
            if (is_done == TIPS_NOT_DONE) {
                queryWrapper.eq(SmsTipsRecord::getIsDone, TIPS_NOT_DONE)
                        .and(lambdaQuery -> lambdaQuery
                                .isNull(SmsTips::getExpirationTime)
                                .or()
                                .gt(SmsTips::getExpirationTime, new Date()));//未过期
            } else {
                queryWrapper.and(lambdaQuery -> lambdaQuery.eq(SmsTipsRecord::getIsDone, TIPS_DONE)
                        .or()
                        .lt(SmsTips::getExpirationTime, new Date()));//过期
            }
        }
        if (appTypeList.size() > 0) {
            queryWrapper.in(SmsTips::getAppName, appTypeList);
        }
        if (!isNullOrEmpty(app_type)) {
            queryWrapper.eq(SmsTips::getAppName, app_type);
        }
        if (!isNullOrEmpty(type)) {
            queryWrapper.eq(SmsTips::getType, type);
        }
        queryWrapper.orderByAsc(SmsTipsRecord::getIsDone)
                .orderByAsc(SmsTips::getExpirationTime)
                .orderByDesc(SmsTips::getCreateTime);
        Page<SmsTipsAndDetailResp> page = new Page<>(pageNum, pageSize);
        smsTipsRecordMpjMapper.selectJoinPage(page, SmsTipsAndDetailResp.class, queryWrapper);

        tipsRespList = page.getRecords().stream().map(smsTips -> {
            SmsTipsResp smsTipsResp = new SmsTipsResp();
            BeanUtils.copyProperties(smsTips, smsTipsResp);
            smsTipsResp.setId(smsTips.getTipsId());
            List<SmsApplication> applicationList = smsApplicationMapper.selectList(new QueryWrapper<SmsApplication>()
                    .lambda()
                    .eq(SmsApplication::getAppType, smsTips.getAppName())
                    .eq(SmsApplication::getAppClient, client));
            if (applicationList.size() > 0) {
                smsTipsResp.setAppPath(applicationList.get(0).getAppPath());
            }

            //查看过期状态
            if (smsTips.getExpirationTime()!=null){
                Date nowDate = new Date();
                long nowTime = nowDate.getTime();
                long endTime = smsTips.getExpirationTime().getTime();
                long leaveTime = endTime - nowTime;
                if (leaveTime <= 0) {
                    //未做操作的通知和待办置为过期状态
                    if (smsTipsResp.getIsDone() == TIPS_NOT_DONE ){
                        smsTipsResp.setIsDone(TIPS_DONE_OVERTIME);
                    }
                }
            }
            return smsTipsResp;
        }).collect(Collectors.toList());
        total = (int) page.getTotal();
        return CommonResult.success(tipsRespList, total);
    }

    @Override
    public ResponseResult getRedPoint(String user_id, Integer client, String app_type) {
        List<SmsApplication> appList = cacheUtil.getAppNameList(user_id, client);
        List<String> appNameList = appList.stream().map(SmsApplication::getAppType).distinct().collect(Collectors.toList());

        MPJLambdaWrapper<SmsTipsRecord> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SmsTipsRecord.class)
                .selectAll(SmsTips.class)
                .selectAs(SmsTipsRecord::getId, "recordId")
                .leftJoin(SmsTips.class, SmsTips::getId, SmsTipsRecord::getTipsId)
                .eq(SmsTipsRecord::getUserId, user_id);

        queryWrapper.eq(SmsTipsRecord::getIsDone, TIPS_NOT_DONE)
                .and(lambdaQuery -> lambdaQuery
                        .isNull(SmsTips::getExpirationTime)
                        .or()
                        .gt(SmsTips::getExpirationTime, new Date()));//未过期
        if (appNameList.size() > 0) {
            queryWrapper.in(SmsTips::getAppName, appNameList);
        }
        if (!isNullOrEmpty(app_type)) {
            queryWrapper.eq(SmsTips::getAppName, app_type);
        }
//        queryWrapper.eq(SmsTips::getType, TIPS_NOT_DONE);
        queryWrapper.orderByAsc(SmsTipsRecord::getIsDone)
                .orderByAsc(SmsTips::getExpirationTime)
                .orderByDesc(SmsTips::getCreateTime);
        List<SmsTipsAndDetailResp> respList = smsTipsRecordMpjMapper.selectJoinList(SmsTipsAndDetailResp.class, queryWrapper);
        Integer count = respList.size();
        return CommonResult.success(count);
    }

    @Transactional
    public Map<String,Object> getTipsRespList(String user_id, Integer type, Integer is_done,
                               Integer pageNum, Integer pageSize, Integer client,
                               String app_type) {
        List<SmsTipsResp> tipsRespList;
        int total;
        List<SmsApplication> appList = cacheUtil.getAppNameList(user_id, client);
        List<String> appNameList = appList.stream().map(SmsApplication::getAppType).collect(Collectors.toList());

        MPJLambdaWrapper<SmsTipsRecord> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SmsTipsRecord.class)
                .selectAll(SmsTips.class)
                .selectAs(SmsTipsRecord::getId, "recordId")
                .leftJoin(SmsTips.class, SmsTips::getId, SmsTipsRecord::getTipsId)
                .eq(SmsTipsRecord::getUserId, user_id);

        if (!isNullOrEmpty(is_done)) {
            if (is_done == TIPS_NOT_DONE) {
                queryWrapper.eq(SmsTipsRecord::getIsDone, TIPS_NOT_DONE)
                        .and(lambdaQuery -> lambdaQuery
                                .isNull(SmsTips::getExpirationTime)
                                .or()
                                .gt(SmsTips::getExpirationTime, new Date()));//未过期
            } else {
                queryWrapper.and(lambdaQuery -> lambdaQuery.eq(SmsTipsRecord::getIsDone, TIPS_DONE)
                        .or()
                        .lt(SmsTips::getExpirationTime, new Date()));//过期
            }
        }
        if (appNameList.size() > 0) {
            queryWrapper.in(SmsTips::getAppName, appNameList);
        }
        if (!isNullOrEmpty(app_type)) {
            queryWrapper.eq(SmsTips::getAppName, app_type);
        }
        if (!isNullOrEmpty(type)) {
            queryWrapper.eq(SmsTips::getType, type);
        }
        queryWrapper.orderByAsc(SmsTipsRecord::getIsDone)
                .orderByAsc(SmsTips::getExpirationTime)
                .orderByDesc(SmsTips::getCreateTime);
        Page<SmsTipsAndDetailResp> page = new Page<>(pageNum, pageSize);
        smsTipsRecordMpjMapper.selectJoinPage(page, SmsTipsAndDetailResp.class, queryWrapper);

        tipsRespList = page.getRecords().stream().map(smsTips -> {
            SmsTipsResp smsTipsResp = new SmsTipsResp();
            BeanUtils.copyProperties(smsTips, smsTipsResp);
            smsTipsResp.setId(smsTips.getTipsId());
            List<SmsApplication> applicationList = smsApplicationMapper.selectList(new QueryWrapper<SmsApplication>()
                    .lambda()
                    .eq(SmsApplication::getAppName, smsTips.getAppName())
                    .eq(SmsApplication::getAppClient, client));
            if (applicationList.size() > 0) {
                smsTipsResp.setAppPath(applicationList.get(0).getAppPath());
            }
            return smsTipsResp;
        }).collect(Collectors.toList());
        total = (int) page.getTotal();
        Map<String,Object> map = new HashMap<>();
        map.put("list",tipsRespList);
        map.put("total",total);
        return map;
    }

    @Override
    public ResponseResult tipsRead(SmsTipsRecordReq tipsRecordReq,String user_id) {
        if (isNullOrEmpty(tipsRecordReq.getIsAll())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (tipsRecordReq.getIsAll() == TIPS_ONE){
            if (isNullOrEmpty(tipsRecordReq.getId())){
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            SmsTipsRecord smsTipsRecord = smsTipsRecordMapper.selectById(tipsRecordReq.getId());
            if (smsTipsRecord == null || smsTipsRecord.getId() == null) {
                return CommonResult.failed(CommonCodeEnum.TIPS_RECORD_ERR);
            }

            smsTipsRecord.setIsDone(TIPS_DONE);
            smsTipsRecordMapper.updateById(smsTipsRecord);
        }else{
            List<SmsTipsRecord> recordList = smsTipsRecordMpjMapper.selectJoinList(SmsTipsRecord.class,new MPJLambdaWrapper<SmsTipsRecord>()
                    .selectAll(SmsTipsRecord.class)
                    .selectAll(SmsTips.class)
                    .leftJoin(SmsTips.class,SmsTips::getId,SmsTipsRecord::getTipsId)
                    .eq(SmsTipsRecord::getIsDone,TIPS_NOT_DONE)
                    .eq(SmsTipsRecord::getUserId,user_id)
                    .eq(SmsTips::getType,TIPS_TYPE_MESSAGE));
            List<String> list = recordList.stream().map(SmsTipsRecord::getTipsId).collect(Collectors.toList());
            if (list.size()>0){
                SmsTipsRecord smsTipsRecord = new SmsTipsRecord();
                smsTipsRecord.setIsDone(TIPS_DONE);
                smsTipsRecordMapper.update(smsTipsRecord,new QueryWrapper<SmsTipsRecord>()
                .lambda()
                .in(SmsTipsRecord::getTipsId,list));
            }
        }
        return CommonResult.success();
    }

}
